package claybird.controller;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import claybird.dao.PersonneDao;
import claybird.dao.ResultDao;
import claybird.dao.TeamDao;
import claybird.dao.ShootDayDao;
import claybird.dom.Handicap.Categorie;
import claybird.dom.Person;
import claybird.dom.Result;
import claybird.dom.ShootDay;
import claybird.dom.Team;

@Controller
public class ShootDayController {
	@Autowired ShootDayDao tirDao;
	@Autowired TeamDao teamDao;
	@Autowired PersonneDao personDao;
	@Autowired ResultDao resultDao;
	
	
	private ModelAndView getModelAndView(ShootDay shootDay){
		ModelAndView mv =new ModelAndView("showshoot","ShootDay",shootDay);
		mv.addObject("pageTitle",shootDay.getName()+" "+shootDay.getStringDate());
		return mv;
	}
	
	@RequestMapping("shoot/calendar")
	public ModelAndView showCalendar(){
		ModelAndView mv =new ModelAndView("showcalendar","shootList",tirDao.getAllTir());
		mv.addObject("pageTitle","Calendrier des tirs");
		return mv;
	}
	
	@RequestMapping("shoot/create")
	public String createShootPage(){
		return "new_shoot";
	}
	
	@RequestMapping("shoot/edit")
	public ModelAndView editShootPage(@RequestParam("id") Long id){
		ShootDay shootDay = tirDao.find(id);
		return getModelAndView(shootDay);
	}
	@RequestMapping("shoot/editlast")
	public ModelAndView editShootPage(){
		ShootDay shootDay = tirDao.findlast();
		return getModelAndView(shootDay);
	}
	@RequestMapping("shoot/showlastresult")
	public ModelAndView showLastShootResult(){

		ShootDay shootDay = tirDao.findlast();
		List<Result> resultSorted = resultDao.findExistingSortedByPoint(shootDay);
		ModelAndView mv = new ModelAndView("showdayresult","resultList",resultSorted);
		mv.addObject("teamLists",teamDao.getAllTeamSortedByResult(shootDay));
		mv.addObject("bestTeamStrength",teamDao.getBestStrength(shootDay));
		return mv;
	}
	@RequestMapping("shoot/show")
	public ModelAndView showShootResult(@RequestParam("idShoot") Long idShoot){

		ShootDay shootDay = tirDao.find(idShoot);
		List<Result> resultSorted = resultDao.findExistingSortedByPoint(shootDay);
		ModelAndView mv = new ModelAndView("showdayresult","resultList",resultSorted);
		mv.addObject("teamLists",teamDao.getAllTeamSortedByResult(shootDay));
		mv.addObject("bestTeamStrength",teamDao.getBestStrength(shootDay));
		return mv;
	}
	
	@RequestMapping("shoot/add")
	public ModelAndView addTir(@RequestParam("name") String name,@RequestParam("location") String location
								,@RequestParam("numberOfClay")byte numberOfClay
								,@RequestParam("day")int day
								,@RequestParam("month")int month
								,@RequestParam("year")int year){
		if(name==""){
			name="tir du "+day +"/"+month+"/"+year;
		}
		Calendar cal = Calendar.getInstance();
		cal.set(year, month-1, day);
		Date date = cal.getTime();
		ShootDay newShoot = new ShootDay(name,location,date,numberOfClay);
		tirDao.persist(newShoot);
		return getModelAndView(newShoot);
	}
	@RequestMapping("shoot/addTeam")
	public ModelAndView addTeam(@RequestParam("name") String name,@RequestParam("idShoot") Long idShoot){
		ShootDay shootDay = tirDao.find(idShoot);
		if (shootDay!=null){
			Team newTeam = new Team(name,shootDay);
			teamDao.persist(newTeam);
		}
		return getModelAndView(shootDay);
	}
	@RequestMapping("shoot/generateteam")
	public ModelAndView generateTeam(@RequestParam("idShoot") Long idShoot){
		ShootDay shootDay = tirDao.find(idShoot);
		if (shootDay!=null){
			ModelAndView mv = new ModelAndView("generateteam","ShootDay",shootDay);
			mv.addObject("listPerson", personDao.getAllPersonne());
			return mv;
		}
		return getModelAndView(shootDay);
	}
	@RequestMapping("shoot/calculate")
	public ModelAndView calculate(@RequestParam("idShoot") Long id){
		ShootDay shootDay = tirDao.find(id);
//		if(resultDao.hasDoubleHighScoreByCategorie(shootDay,Categorie.amateur)){
//			ModelAndView mv = this.getModelAndView(shootDay);
//			mv.addObject("error","plusieurs meilleurs résultats pour la catégorie amateur");
//			return mv;
//		}
//		if(resultDao.hasDoubleHighScoreByCategorie(shootDay,Categorie.chasseur)){
//			ModelAndView mv = this.getModelAndView(shootDay);
//			mv.addObject("error","plusieurs meilleurs résultats pour la catégorie chasseur");
//			return mv;
//		}
//		if(resultDao.hasDoubleHighScoreByCategorie(shootDay,Categorie.invite)){
//			ModelAndView mv = this.getModelAndView(shootDay);
//			mv.addObject("error","plusieurs meilleurs résultats pour la catégorie invite");
//			return mv;
//		}
//		if(resultDao.hasDoubleHighScoreByCategorie(shootDay,Categorie.pro)){
//			ModelAndView mv = this.getModelAndView(shootDay);
//			mv.addObject("error","plusieurs meilleurs résultats pour la catégorie pro");
//			return mv;
//		}
//		if(resultDao.hasDoubleHighScoreByCategorie(shootDay,Categorie.tireur)){
//			ModelAndView mv = this.getModelAndView(shootDay);
//			mv.addObject("error","plusieurs meilleurs résultats pour la catégorie tireur");
//			return mv;
//		}
		List<Result> resultSorted = resultDao.findExistingSortedByPoint(shootDay);
		float lastRes = 0;
		Short total = 0;
		Short current=1;
		float lastResWithGuest = 0;
		Short totalWithGuest = 0;
		Short currentWithGuest=1;
		for(Result res: resultSorted){
			if(!res.getPerson().isGuest()){
				total++;
				if(lastRes>res.getRealValue()){
					current = (short) (total);
				}
				res.setRanking(current);
				lastRes =res.getRealValue();
			}
			totalWithGuest++;
			if(lastResWithGuest>res.getRealValue()){
				currentWithGuest = (short) (totalWithGuest);
			}
			res.setRankingWithGuest(currentWithGuest);
			lastResWithGuest =res.getRealValue();
			resultDao.persist(res);
		}
		Team bestTeam = null;
		Team bestTeamWithGuest = null;
		for(Team tm:shootDay.getListOfTeam()){
			tm.setTotalResult(0);
			tm.setAverageHandicap(0);
			if (bestTeam==null || tm.getAverageHandicap()> bestTeam.getAverageHandicap()){
				bestTeam = tm;
			}
			if (bestTeamWithGuest==null || tm.getAverageHandicap()> bestTeamWithGuest.getAverageHandicap()){
				bestTeamWithGuest = tm;
			}
		}
		float bestTeamStrength= bestTeam.getAverageHandicap();
		List<Team> sortedTeamByPoint = new ArrayList<Team>();
		for(Team tm:shootDay.getListOfTeam()){
			boolean added = false;
			for (int i=0; i<sortedTeamByPoint.size();i++){
				if (tm.getTeamValue(bestTeamStrength)>sortedTeamByPoint.get(i).getTeamValue(bestTeamStrength) ){
					sortedTeamByPoint.add(i, tm);
					added=true;
					break;
				}
			}
			if (!added){
				sortedTeamByPoint.add(tm);
			}
		}
		float bestTeamStrengthWithGuest= bestTeamWithGuest.getAverageHandicap();
		List<Team> sortedTeamByPointWithGuest = new ArrayList<Team>();
		for(Team tm:shootDay.getListOfTeam()){
			boolean added = false;
			for (int i=0; i<sortedTeamByPointWithGuest.size();i++){
				if (tm.getTeamValueWithGuest(bestTeamStrengthWithGuest)>sortedTeamByPointWithGuest.get(i).getTeamValueWithGuest(bestTeamStrengthWithGuest) ){
					sortedTeamByPointWithGuest.add(i, tm);
					added=true;
					break;
				}
			}
			if (!added){
				sortedTeamByPointWithGuest.add(tm);
			}
		}
		short currentRanking =1;
		for(short i=0; i<sortedTeamByPoint.size();i++){
			
			if  (i>0&&sortedTeamByPoint.get(i).getTeamValue(bestTeamStrength)<sortedTeamByPoint.get(i-1).getTeamValue(bestTeamStrength)){
				
				currentRanking=(short) (i+1);
			}
			sortedTeamByPoint.get(i).setRanking(currentRanking);
			teamDao.persist(sortedTeamByPoint.get(i));
			
		}
		currentRanking =1;
		for(short i=0; i<sortedTeamByPointWithGuest.size();i++){
			
			if  (i>0&&sortedTeamByPointWithGuest.get(i).getTeamValueWithGuest(bestTeamStrengthWithGuest)<sortedTeamByPointWithGuest.get(i-1).getTeamValueWithGuest(bestTeamStrengthWithGuest)){
				
				currentRanking=(short) (i+1);
			}
			sortedTeamByPointWithGuest.get(i).setRankingWithGuest(currentRanking);
			teamDao.persist(sortedTeamByPointWithGuest.get(i));
			
		}
		
		//UPDATE HANDICAP
		for(Person person: shootDay.getAllPlayers()){
			if (resultDao.hasEnoughResult(person, shootDay.getYear())){
				if (person.getLastHandicap().getCurrentHandicap()<resultDao.findExisting(shootDay, person).getPercentNewHandicap()){
					person.getLastHandicap().setCurrentHandicap(resultDao.findExisting(shootDay, person).getPercentNewHandicap());
				}
			}else{
				person.getLastHandicap().setCurrentHandicap(resultDao.findExisting(shootDay, person).getPercentNewHandicap());
			}
			personDao.persist(person);
		}
		
		ModelAndView mv = new ModelAndView("showdayresult","resultList",resultDao.findExistingSortedByRanking(shootDay));
		mv.addObject("teamLists",sortedTeamByPoint);
		mv.addObject("teamListsWithGuest",sortedTeamByPointWithGuest);
		mv.addObject("bestTeamStrength",bestTeamStrength);
		return mv;
	}
}
